package core;

/* Import the UIManager here!!
 *import src.fieldgame.UIManager;
 */

import translate.Translate;
import boundary.GUIManager;
import boundary.UI;
import entities.Inventory;
import fields.Ownable;
import gstd.*;
import fields.*;

public class GameManager extends GameManagerAbs {
	private UI ui;
	private int currentPlayerIndex;
	final int START_BALANCE = 30000;

	@Override
	public void endMatch() {
		// get winner
		Player winner = getWinner();
		ui.showWinner(winner);
		// if player does not select start new match, exit system

	}

	@Override
	public void initialize() {
		shaker = new Shaker(2, 6);
		Field[] fields = new Field[] {
				new Territory(Translate.print("Tribe Encampment"), 100, 1000),
				new Territory(Translate.print("Crater"), 300, 1500),
				new Tax(Translate.print("Goldmine"), 2000, 0),
				new Territory(Translate.print("Mountain"), 500, 2000),
				new Fleet(Translate.print("Second Sail"), 4000),
				new Territory(Translate.print("Cold Dessert"), 700, 3000),
				new Territory(Translate.print("Black Cave"), 1000, 4000),
				new LaborCamp(Translate.print("Huts in the Mountain"), 100, 2500),
				new Territory(Translate.print("The Werewall"), 1300, 4300),
				new Territory(Translate.print("Mountain Village"), 1600, 4750),
				new Fleet(Translate.print("Sea Grover"), 4000),
				new Refuge(Translate.print("Walled City"), 5000),
				new Territory(Translate.print("South Citadel"), 2000, 5000),
				new Territory(Translate.print("Palace Gates"), 2600, 5500),
				new Fleet(Translate.print("The Buccaneers"), 4000),
				new LaborCamp(Translate.print("The Pit"), 100, 4000),
				new Tax(Translate.print("Caravan"), 4000, 0.1),
				new Refuge(Translate.print("Monastery"), 500),
				new Fleet(Translate.print("Privateer Armada"), 4000),
				new Territory(Translate.print("Tower"), 3200, 6000),
				new Territory(Translate.print("Castle"), 4000, 8000) };
		gameBoard = new GameBoard(fields);

		ui = new GUIManager();

		ui.init(true, gameBoard.getFields());

		int numberOfPlayers = ui.selectNumberOfPlayers();
		Player[] players = new Player[numberOfPlayers];
		for (int i = 0; i < numberOfPlayers; i++) {
			String name = "";
			do { // ask player to input a name for as long as the input is empty or the name is already taken
				name = ui.inputPlayerName(i);
			} while (name.isEmpty() || nameIsNotUsed(name, players));
			players[i] = new Player(name, new Inventory(START_BALANCE));
		}
		
		// use this to create a set number of players with set names without user interaction
		// Player[] players = new Player[4];
		// for (int i = 0; i < players.length; i++) {
		// players[i] = new Player(Translate.print("player %d",i+1), new Inventory(START_BALANCE));
		// }
		
		playerList = new PlayerList(players);
		ui.createPlayers(playerList.getPlayers());
	}

	// return true if a name is taken by another player, false if its not used
	private boolean nameIsNotUsed(String name, Player[] players) {
		for (int i = 0; i < players.length; i++) {
			if (players[i] != null)
				if (name.equals(players[i].getName()))
					return true;

		}
		return false;
	}

	@Override
	public boolean isMatchDone() {
		return true;
	}

	@Override
	public boolean isRoundDone() {
		Player[] players = playerList.getPlayers();
		int playerCounter = 0;
		for (int i = 0; i < players.length; i++) {
			if (players[i].getInventory().getBalance() >= 0)
				playerCounter++;
		}

		return playerCounter == 1;
	}

	@Override
	public void match() {
		if (!ui.selectStartNewMatch())
			System.exit(0);

		// reset game
		turnCounter = 0; // remove this later
		Player[] players = playerList.getPlayers();
		for (int i = 0; i < players.length; i++) {
			// players[i].getInventory().setBalance(START_BALANCE);
			players[i] = new Player(players[i].getName(), new Inventory(START_BALANCE));
			((Inventory) players[i].getInventory()).reset();
		}
		ui.resetBoard(gameBoard.getFields(), playerList.getPlayers());
	}

	@Override
	public void turn() {

		Player currentPlayer = playerList.getPlayer(currentPlayerIndex);

		// ignore bankrupt players
		if (hasNegativeBalance(currentPlayer)) {
			nextPlayer();
			return;
		}

		// select roll dice, generate dice and get dice sum
		ui.selectShake(currentPlayer); // button to roll in GUI
		ui.showDices(shaker.shake()); // show/update dices in GUI

		// find the field the player will move to
		int nextFieldIndex = currentPlayer.getfieldIndex() + shaker.getDiceSum();
		nextFieldIndex %= gameBoard.getFields().length;

		// move player to field
		currentPlayer.setFieldIndex(nextFieldIndex);
		ui.move(nextFieldIndex, currentPlayer); // put player on field in GUI
		Field currentField = gameBoard.getField(nextFieldIndex);

		// if the field is Ownable, has no owner and the player can afford it
		// ask if player wants to buy it
		if (currentField instanceof Ownable) {
			Ownable ownableField = (Ownable) currentField;
			if (ownableField.getOwner() == null && currentPlayer.getInventory().getBalance() >= ownableField.getPrice()) {
				ownableField.setBuyFieldDecision(ui.askToBuy(ownableField, currentPlayer));
			}

			// if player land on an owned Ownable field that belongs to another player, display message in GUI
			if (ownableField.getOwner() != null && ownableField.getOwner() != currentPlayer)
				ui.payRent(currentPlayer, ownableField.getOwner(), ownableField.getRent()); // player A paid XXXX rent to player B
		}

		// if player land on a Tax field, display message in GUI
		if (currentField.getClass() == Tax.class) {
			// Display the 10% paid

			if (currentField.getName().equals("Goldmine"))
				ui.payTax(currentPlayer, ((Tax) currentField).getTax());
			if (currentField.getName().equals("Caravan"))
				if (((Tax) currentField).getTax() > 0.1 * ((Inventory) currentPlayer.getInventory()).getTotalAssets())
					ui.payTax(currentPlayer, ((int) (0.1 * ((Inventory) currentPlayer.getInventory()).getTotalAssets()))); // player pays 10% of their inventory
				else
					ui.payTax(currentPlayer, ((Tax) currentField).getTax()); // player pays XXXX

		}

		// if player land on a Refuge field, display message in GUI
		if (currentField.getClass() == Refuge.class)
			ui.receiveBonus(currentPlayer, ((Refuge) currentField).getBonus()); // player gains XXXX to balance

		// execute field logic and update GUI (players and fields)
		currentField.landOnField(currentPlayer);
		ui.updatePlayers(playerList.getPlayers()); // update player balance in GUI
		ui.updateBoard(gameBoard.getFields()); // update fields ownership in GUI

		// if player is bankrupt, remove ownership from fields, update GUI
		if (hasNegativeBalance(currentPlayer)) {
			((Inventory) currentPlayer.getInventory()).reset();
			ui.setPlayerBankrupt(currentPlayer, gameBoard.getFields()); // player lose fields in GUI
		}

		nextPlayer();
	}

	private boolean hasNegativeBalance(Player currentPlayer) {
		return currentPlayer.getInventory().getBalance() < 0;
	}

	private void nextPlayer() {
		currentPlayerIndex++;
		currentPlayerIndex %= playerList.getPlayers().length;
	}

	private Player getWinner() {
		Player winner = null;
		Player[] players = playerList.getPlayers();
		for (int i = 0; i < players.length; i++)
			if (players[i].getInventory().getBalance() > 0) {
				winner = players[i];
				break;
			}
		return winner;
	}

	int turnCounter; // is reset in endMatch()



	@Override
	public void endRound() {
		// not used
	}

	@Override
	public void round() {
		// not used
	}
}
